﻿//-----------------------------------------------------------------------
// <copyright file="GenerateCategoryMap.cs" company="Microsoft">
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <summary>Tool to generate string ids based on a strings.xml file</summary>
//-----------------------------------------------------------------------

namespace Microsoft.Mediaroom.TestLogging
{
    using System.Collections.Generic;
    using System.IO;
    using System;

    /// <summary>
    /// Main Program.
    /// </summary>
    public class GenerateCategoryMap
    {
        /// <summary>
        /// Main function.
        /// </summary>
        /// <param name="args">Command-line params.</param>
        public static void Main(string[] args)
        {
            var clp = new CommandLineParser(args);

            try
            {
                if (clp.Exists('?'))
                {
                    Usage();
                    return;
                }

                if (clp.Exists('f') && clp.Exists('o'))
                {
                    // Storage for errors found 
                    var errors = new List<string>();

                    // Get arguments from commandline
                    string categoriesXmlPath = clp.GetStringForSwitch('f');
                    string categoriesTargetPath = clp.GetStringForSwitch('o');

                    // Load the strings.xml file
                    Console.WriteLine("Load '" + categoriesXmlPath + "'");
                    LogCategoryContainer.Load(categoriesXmlPath);

                    // Create file to be output 
                    Console.WriteLine("Output '" + categoriesTargetPath + "'");
                    var outputFile = new StreamWriter(categoriesTargetPath);

                    // Note: This should be template driven - but for moment it is hard coded
                    outputFile.Write(
@"//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.1434
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Microsoft.Mediaroom.TestLogging
{
    ");

                    #region static strings class generation

                    //// HACKHACK Yuck - this needs refactoring - big time...  I haven't got time to do this now...
                    if (clp.Exists('s'))
                    {
                        outputFile.Write(
@"  
    /// <summary>
    /// Codegened static class.
    /// </summary>
    public sealed class TraceCategories 
    {
        private TraceCategories() 
        { 
        }

");
                        // Iterate through all identifiers in strings.xml and output const string
                        foreach (string idvalue in LogCategoryContainer.CategoryNames)
                        {
                            // Replace characters that cannot be used for identifiers with '_'
                            // Note: This is how the identifiers should be created
                            // string newIdentifier = idvalue.Key.Replace(".", "_");
                            // newIdentifier = identifier.Replace("-", "_");

                            // Note: This way is compatible with the existing naming conventions
                            string newIdentifier = idvalue.Replace(".", "");
                            newIdentifier = newIdentifier.Replace("-", "");
                            newIdentifier = newIdentifier.Replace(" ", "");

                            // If whitespace exists in identifier this it is an error
                            string trimmedNewIdentifier = newIdentifier.Trim();
                            if (newIdentifier != trimmedNewIdentifier)
                            {
                                errors.Add("'" + trimmedNewIdentifier + "' has whitespace in the identifier");
                            }

                            string realIdentifier = idvalue;
                            string trimmedRealIdentifier = realIdentifier.Trim();

                            outputFile.WriteLine("        /// <summary>");
                            outputFile.WriteLine("        /// Constant string value {0}.", trimmedRealIdentifier);
                            outputFile.WriteLine("        /// </summary>");
                            outputFile.WriteLine("        public const string {0} = \"{0}\";", trimmedNewIdentifier);
                            outputFile.WriteLine("");
                        }

                        outputFile.Write(
@"  }

");
                    }

                    #endregion

                    #region Enum generation

                    //// HACKHACK Yuck - this needs refactoring - big time...  I haven't got time to do this now...
                    if (clp.Exists('e'))
                    {
                        outputFile.Write(
@"  
    /// <summary>
    /// Codegened enumeration
    /// </summary>
    public enum LogCategoriesEnum {
");

                        // Iterate through all identifiers in strings.xml and output const string
                        foreach (string idvalue in LogCategoryContainer.CategoryNames)
                        {
                            // Replace characters that cannot be used for identifiers with '_'
                            // Note: This is how the identifiers should be created
                            // string newIdentifier = idvalue.Key.Replace(".", "_");
                            // newIdentifier = identifier.Replace("-", "_");

                            // Note: This way is compatible with the existing naming conventions
                            string newIdentifier = idvalue.Replace(".", "");
                            newIdentifier = newIdentifier.Replace("-", "");
                            newIdentifier = newIdentifier.Replace(" ", "");

                            // If whitespace exists in identifier this it is an error
                            string trimmedNewIdentifier = newIdentifier.Trim();
                            if (newIdentifier != trimmedNewIdentifier)
                            {
                                errors.Add("'" + trimmedNewIdentifier + "' has whitespace in the identifier");
                            }

                            string realIdentifier = idvalue;
                            string trimmedRealIdentifier = realIdentifier.Trim();

                            outputFile.WriteLine("        /// <summary>");
                            outputFile.WriteLine("        /// Enum value {0}.", trimmedRealIdentifier);
                            outputFile.WriteLine("        /// </summary>");
                            outputFile.WriteLine("        {0},", trimmedNewIdentifier);
                            outputFile.WriteLine("");
                        }

                        outputFile.Write(
@"  }

");
                    }

                    #endregion

                    #region LogCategories generation

                    outputFile.Write(
@"    /// <summary>
    /// Codegened class
    /// </summary>
    public static class LogCategories
    {
");

                    // Iterate through all identifiers in strings.xml and output const string
                    foreach (string idvalue in LogCategoryContainer.CategoryNames)
                    {
                        // Replace characters that cannot be used for identifiers with '_'
                        // Note: This is how the identifiers should be created
                        // string newIdentifier = idvalue.Key.Replace(".", "_");
                        // newIdentifier = identifier.Replace("-", "_");

                        // Note: This way is compatible with the existing naming conventions
                        string newIdentifier = idvalue.Replace(".", "");
                        newIdentifier = newIdentifier.Replace("-", "");
                        newIdentifier = newIdentifier.Replace(" ", "");

                        // If whitespace exists in identifier this it is an error
                        string trimmedNewIdentifier = newIdentifier.Trim();
                        if (newIdentifier != trimmedNewIdentifier)
                        {
                            errors.Add("'" + trimmedNewIdentifier + "' has whitespace in the identifier");
                        }

                        string realIdentifier = idvalue;
                        string trimmedRealIdentifier = realIdentifier.Trim();

                        outputFile.WriteLine("        /// <summary>");
                        outputFile.WriteLine("        /// Get Id {0}", trimmedRealIdentifier);
                        outputFile.WriteLine("        /// </summary>");
                        outputFile.WriteLine("        public static LogCategory {0}", trimmedNewIdentifier);
                        outputFile.WriteLine("        {");
                        outputFile.WriteLine("            get{ return LogCategoryContainer.GetCategoryByName(\"" + trimmedRealIdentifier + "\"); }");
                        outputFile.WriteLine("        }");
                        outputFile.WriteLine("");
                    }

                    outputFile.Write(
@"
        /// <summary>
        /// Proxy for MapNonExistentCategory flag in LogCategoriesContainer.
        /// </summary>
        /// <param name=""flag"">True maps non existent categories to the default.</param>
        public static void MapNonExistentCategory(bool flag)
        {
            LogCategoryContainer.MapNonExistentToDefault = flag;
        }

        /// <summary>
        /// Proxy for GetCategoryByName in LogCategoriesContainer.
        /// </summary>
        /// <param name=""name"">Name of category.</param>
        /// <returns>The requested LogCategory.</returns>
        public static LogCategory GetCategoryByName(string name)
        {
            return LogCategoryContainer.GetCategoryByName(name);
        }

        /// <summary>
        /// Proxy for GetCategoryByID in LogCategoriesContainer
        /// </summary>
        /// <param name=""id"">Id of category.</param>
        /// <returns>The requested LogCategory.</returns>
        public static LogCategory GetCategoryById(int id)
        {
            return LogCategoryContainer.GetCategoryById(id);
        }
    }
}
");

                    #endregion

                    // Close output file and output errors
                    outputFile.Close();
                    Console.WriteLine("Complete - {0} Error(s) found", errors.Count);

                    for (int i = 0; i < errors.Count; i++)
                    {
                        ConsoleColor save = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine(errors[i]);
                        Console.ForegroundColor = save;
                    }
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Missing command line parameter");
                    Console.ResetColor();
                    Usage();
                }
            }
            catch (Exception e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Something bad happened...");
                Console.ResetColor();
                Console.WriteLine(e.Message);
            }
        }

        /// <summary>
        /// Show usage.
        /// </summary>
        private static void Usage()
        {
            ConsoleColor save = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("GenerateCategoryMap.exe");
            Console.WriteLine("==========================================================");
            Console.WriteLine("");
            Console.WriteLine("==========================================================");
            Console.WriteLine("-f Categories.xml");
            Console.WriteLine("-o <targetpath>\\LogCategoryIds.cs");
            Console.WriteLine("==========================================================");
            Console.WriteLine("Optional:");
            Console.WriteLine("-? Usage info (this information you are reading now...)");
            Console.WriteLine("-e Create enumeration of log categories");
            Console.WriteLine("");
            Console.WriteLine("i.e. ");
            Console.WriteLine("GenerateCategoryMap -f Categories.xml -o LogCategoryIds.cs");
            Console.WriteLine("");
            Console.ForegroundColor = save;
            Console.ResetColor();
        }
    }
}
